package it.softphone.cmc.server.rest;

import it.softphone.cmc.server.service.BundleService;
import it.softphone.cmc.server.service.exception.CMCException;
import it.softphone.commons.service.LogAware;
import it.softphone.commons.spring.ApplicationConfig;

import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSelectInfo;
import org.apache.commons.vfs.FileSelector;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemManager;
import org.apache.commons.vfs.FileType;

import com.sun.jersey.core.header.ContentDisposition;
import com.sun.jersey.multipart.FormDataBodyPart;
import com.sun.jersey.multipart.FormDataMultiPart;

/**
 * 
 * @author softphone
 *
 */
@Path("/bundle")
public class CMCBundleManager implements LogAware {

	/**
	 * 
	 * @return virtual file system instance
	 */
	protected FileSystemManager vfs() {

		FileSystemManager service = ApplicationConfig.getBean(FileSystemManager.class);

		return service;
		
	}

	protected BundleService bundle() {

		BundleService service = ApplicationConfig.getBean(BundleService.class);

		return service;
		
	}
	
    private FileObject addBundleJar(final FileObject bundleFolder, final FormDataBodyPart bundle) throws Exception {

    	final ContentDisposition cd = bundle.getContentDisposition();
    	if( cd == null ) {
    		throw new IllegalArgumentException( "content disposition is null!");
    	}
    	
		final String filePath = cd.getFileName();
    	if( filePath == null ) {
    		throw new IllegalArgumentException( "file Path is null!");
    	}
		
		logger.info( String.format("try to resolve file [%s]", filePath) );
		
    	final FileObject file = bundleFolder.resolveFile( filePath );
    	
    	if( !file.exists() ) {

        	final java.io.InputStream is = bundle.getValueAs(java.io.InputStream.class);

    		final byte[] bytes = it.softphone.commons.util.Util.toBytes(is, 512);

    		file.createFile();
    		
    		file.getContent().getOutputStream().write(bytes);
    		
    		file.getContent().close();
    		
    	}
    	return file;
    }
    
    
    private FileObject getBundleFolder( final String bundlePath ) throws FileSystemException {

    	final FileObject folder = vfs().resolveFile( bundlePath );
    	
    	if( !folder.exists() ) {
    	
    		folder.createFolder();
    		
    	}
    	
    	if( !FileType.FOLDER.equals(folder.getType()) ) {
    		throw new FileSystemException( String.format("[%s] is not a folder", bundlePath));
    	}
    	
    	return folder;
    }

	private BundleService.Bundle newBundle(FormDataMultiPart part ) throws CMCException
	{
		
		final FormDataBodyPart bundleName = part.getField("bundleName");
		if( bundleName == null ) {			
			throw new CMCException("No 'bundleName' parameter provided!");
		}
		
		
		final List<FormDataBodyPart> bundleList = part.getFields("bundleList");
		
		if( bundleList == null || bundleList.isEmpty()) {		
			throw new CMCException("No 'bundleList' parameter provided!");
		}
		
		try {
			
			final FileObject folder = getBundleFolder(bundleName.getValue());

			for( FormDataBodyPart bundle : bundleList) {
			
				addBundleJar(folder, bundle);
				
			}
		
			BundleService.Bundle result = bundle().createBundle(folder);
			
			
			return result;
		}
		catch( Exception e ) {
			final String message = "error adding bundle to virtual file system";
			logger.error( message, e );
			throw new CMCException(message);
			
		}
	
		  
	}

    
	/**
	 * 
	 * @param part
	 * @return
	 * @throws CMCException
	 */
	@POST 
	@Produces(MediaType.TEXT_PLAIN)
    @Consumes(MediaType.MULTIPART_FORM_DATA) 
	//@RequiresPermissions(  Permissions.Tenant.CREATE )
	public Response createBundle(FormDataMultiPart part ) throws CMCException
	{
		
		BundleService.Bundle result = newBundle(part);
		
		
		try {
			/*
			final FileObject folder =  vfs().resolveFile( result.getPath() );

			final StringBuilder sb = new StringBuilder();

			folder.findFiles( new FileSelector() {
				
				@Override
				public boolean traverseDescendents(FileSelectInfo fileInfo)
						throws Exception {
					return true; //fileInfo.getFile().getType().equals(FileType.FOLDER);
				}
				
				@Override
				public boolean includeFile(FileSelectInfo fileInfo) throws Exception {
					
					sb.append( fileInfo.getFile().getName().getBaseName() )
					.append(':')
					.append( fileInfo.getFile().getName().getExtension() )
					.append(':')
					.append( fileInfo.getFile().getName().getPath())
					.append('\n');
					
					return true;
				}
			});
			*/
			return Response
					.ok()
					.entity(result.getId())
					.build();

		}
		catch( Exception e ) {
			final String message = "error adding bundle to virtual file system";
			logger.error( message, e );
			return Response.serverError().entity(message).build();
			
		}
	
		  
	}


}
